
#include <BOpenGL>
#include "member_BPicker.h"
#include "member_BGroup.h"
#include "member_BNode.h"
#include "member_BShape.h"
#include "member_BPicker.h"
#include "member_BPickItem.h"
#include "member_BBillboard.h"

using namespace BWE;

member_BPicker::member_BPicker(BPicker* picker)
{
	boss = picker;
	group = 0;
	node = 0;
	shape = 0;
	hitNum = 1;
}
member_BPicker::~member_BPicker()
{

}

void member_BPicker::enter(const BLine& line, BGroup* group)
{
	if (!group_member(group)->visible)
		return;
	if (exclusions.contain(group))
		return;

	const BSpace& space = group->space();
	if (!space.contain(line.begin()) && !space.contain(line.end()))
	{
		if (false == line.intersect(space))
			return;
	}

	this->group = group;
	for (int i = 0; i < group->shapeCount(); i++)
	{
		BShape* shape = group->shape(i);
		this->enter(line, shape);
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		BNode* node = group->node(i);
		this->enter(line, node);
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		BGroup* child = group->child(i);
		this->enter(line, child);
	}
	this->group = 0;
}
void member_BPicker::enter(const BLine& line, BNode* node)
{
	if (!node_member(node)->visible)
		return;
	if (exclusions.contain(node))
		return;

	BMatrix matrix = node->matrix();
	matrix.inverse();
	BLine localLine = line * matrix;

	const BBox& box = node->box();
	if (!box.contain(localLine.begin()) && !box.contain(localLine.end()))
	{
		if (false == localLine.intersect(box))
			return;
	}

	this->node = node;
	if (ShapeOctTree* shapeOctTree = node_member(node)->shapeSpaceTree)
	{
		shapeOctTree->intersect(line, shapeOctItems);
		for (int si = 0; si < shapeOctItems.size(); si++)
		{
			BShapeArray& shapes = *shapeOctItems[si];
			for (int i = 0; i < shapes.size(); i++)
			{
				BShape* shape = shapes(i);
				if (!shape->visible())
					continue;
				if (exclusions.contain(shape))
					continue;
				this->enter(localLine, shape);
			}
		}
	}
	else
	{
		for (int i = 0; i < node->shapeCount(); i++)
		{
			BShape* shape = node->shape(i);
			if (!shape->visible())
				continue;
			if (exclusions.contain(shape))
				continue;
			this->enter(localLine, shape);
		}
	}
	this->node = 0;
	return;
}
void member_BPicker::enter(const BLine& line, BShape* shape)
{
	if (!shape_member(shape)->visible)
		return;
	if (exclusions.contain(shape))
		return;

	BMatrix matrix = shape->matrix();
	matrix.inverse();
	BLine localLine = line * matrix;

	BBox box = shape->box();
	if (!box.contain(localLine.begin()) && !box.contain(localLine.end()))
	{
		if (false == localLine.intersect(box))
			return;
	}

	this->shape = shape;
	if (BSphere* sphere = dynamic_cast<BSphere*>(shape))
	{
		boss->pick(localLine, sphere);
	}
	else if (BGeoSphere* geosphere = dynamic_cast<BGeoSphere*>(shape))
	{
		boss->pick(localLine, geosphere);
	}
	else if (BCylinder* cylinder = dynamic_cast<BCylinder*>(shape))
	{
		boss->pick(localLine, cylinder);
	}
	else if (BMesh* mesh = dynamic_cast<BMesh*>(shape))
	{
		boss->pick(localLine, mesh);
	}
	else if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
	{
		boss->pick(localLine, geometry);
	}
	else if (BBillboard* billboard = dynamic_cast<BBillboard*>(shape))
	{
		boss->pick(localLine, billboard);
	}
	else if (BTerrain* terrain = dynamic_cast<BTerrain*>(shape))
	{
		boss->pick(localLine, terrain);
	}
	else if (BSurface* surface = dynamic_cast<BSurface*>(shape))
	{
		boss->pick(localLine, surface);
	}
	else
	{
		boss->pick(localLine, shape);
	}
	this->shape = 0;
}

